#include <iostream>
#include "list.h"
using namespace std;

template <class Object>
List<Object>::List()
{
	header = new ListNode<Object>;
}

template <class Object>
bool List<Object>::isEmpty() const
{
	return header->next == NULL;
}

template <class Object>
ListItr<Object> List<Object>::zeroth() const
{
	return ListItr<Object>(header);
}

template <class Object>
ListItr<Object> List<Object>::first() const
{
	return ListItr<Object>(header->next);
}

template <class Object>
void printList(const List<Object> & theList)
{
	if (theList.isEmpty())
		cout << "Empty list" << endl;
	else {
		ListItr<Object> itr = theList.first();
		for (; !itr.isPastEnd(); itr.advance())
			cout << itr.retrieve() << " ";
	}

	cout << endl;
}

template <class Object>
ListItr<Object> List<Object>::find(const Object & x) const
{
	ListNode<Object> *itr = header->next;

	while (itr != NULL && itr->element != x)
		itr = itr->next;

	return ListItr<Object>(itr);
}

template <class Object>
void List<Object>::remove(const Object & x)
{
	ListItr<Object> p = findPrevious(x);

	if (p.current->next != NULL){
		ListNode<Object> *oldNode = p.current->next;	
		p.current->next = p.current->next->next;
		delete oldNode;
	}
}

template <class Object>
ListItr<Object> List<Object>::findPrevious(const Object & x) const
{
	ListNode<Object> *itr = header;

	while (itr->next != NULL && itr->next->element != x)
		itr = itr->next;

	return ListItr<Object>(itr);
}

template <class Object>
void List<Object>::insert(const Object & x, const ListItr<Object> & p)
{
	if (p.current != NULL)
		p.current->next = new ListNode<Object>(x, p.current->next);
}

template <class Object>
void List<Object>::makeEmpty()
{
	while (! isEmpty())
		remove(first().retrieve());
}

template <class Object>
List<Object>::~List()
{
	makeEmpty();
	delete header;
}

template <class Object>
const List<Object> & List<Object>::operator=(const List<Object> & rhs)
{
	if (this != &rhs) {
		makeEmpty();

		ListItr<Object> ritr = rhs.first();
		ListItr<Object> itr = zeroth(); 
		for (; !ritr.isPastEnd(); ritr.advance(), itr.advance())
			insert(ritr.retrieve(), itr);
	}
	return *this;	
}

template <class Object>
List<Object>::List(const List<Object> & rhs)
{
	header = new ListNode<Object>;
	*this = rhs;
}

/*
 *int main()
 *{
 *    
 *}
 */
